/*===========================================================================
  Copyright (C) 2014 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.v2.common.om.impl;

import java.util.concurrent.ConcurrentHashMap;

import net.sf.okapi.v2.common.LocaleId;
import net.sf.okapi.v2.common.U;
import net.sf.okapi.v2.common.exceptions.InvalidParameterException;
import net.sf.okapi.v2.common.om.GetTarget;
import net.sf.okapi.v2.common.om.IStore;
import net.sf.okapi.v2.common.om.ITextContainer;
import net.sf.okapi.v2.common.om.ITextFragment;
import net.sf.okapi.v2.common.om.ITextUnit;

/**
 * Implements {@link ITextUnit}.
 */
public class TextUnit extends GroupOrUnit implements ITextUnit {

	private IStore store;
	private ITextContainer source;
    private ConcurrentHashMap<LocaleId, ITextContainer> targets;

    /**
     * Creates a new {@link ITextUnit} object with a given id.
     * @param id the id of this unit (must not be null or empty).
     */
	public TextUnit (String id) {
		if ( U.isNoE(id) ) {
			throw new InvalidParameterException("Id must not be null or empty.");
		}
		this.id = id;
		store = new Store(this);
		targets = new ConcurrentHashMap<>(1);
		source = new TextContainer(store, null);
	}
	
	@Override
	public IStore getStore () {
		return store;
	}

	@Override
	public ITextContainer getSource () {
		return source;
	}

	@Override
	public ITextContainer getTarget (LocaleId trgLoc) {
		return targets.get(trgLoc);
	}

	@Override
	public ITextContainer getTarget (LocaleId trgLoc,
		GetTarget option)
	{
		ITextContainer tc = targets.get(trgLoc);
		if ( tc != null ) return tc;
		// Else: fall back to the selected option
		switch ( option ) {
		case CLONE_SOURCE:
			tc = new TextContainer(source, store, trgLoc);
			targets.put(trgLoc, tc);
			return tc;
		case CREATE_EMPTY:
			tc = new TextContainer(store, trgLoc);
			targets.put(trgLoc, tc);
			return tc;
		case DONT_CREATE:
			// Return null
		}
		return null;
	}

	@Override
	public boolean hasTarget (LocaleId trgLoc) {
		return targets.containsKey(trgLoc);
	}

	@Override
	public Object getObject (String id) {
		// Check the source container
		for ( ITextFragment part : source ) {
			// The part's id can be null: equals should support that
			if ( id.equals(part.getId()) ) return part;
		}
		// Check the targets
		for ( ITextContainer trgCont : targets.values() ) {
			for ( ITextFragment part : trgCont ) {
				// The part's id can be null: equals should support that
				if ( id.equals(part.getId()) ) return part;
			}
		}
		// Check the tags
		return store.getFirstTag(id);
	}
	
	@Override
	public boolean isIdUsed (String id) {
		return (getObject(id) != null);
	}

}
